package flex.cc.uac.service.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import javax.annotation.Resource;

import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import flex.cc.PublicUtil;
import flex.cc.base.dto.LoginAuthDto;
import flex.cc.base.enums.ErrorCodeEnum;
import flex.cc.uac.constant.MenuConstant;
import flex.cc.uac.dao.UacMenuDao;
import flex.cc.uac.entity.UacMenuEntity;
import flex.cc.uac.entity.UacRoleMenuEntity;
import flex.cc.uac.enums.UacMenuStatusEnum;
import flex.cc.uac.exceptions.UacBizException;
import flex.cc.uac.service.UacMenuService;
import flex.cc.uac.vo.ViewMenuVo;
import lombok.extern.slf4j.Slf4j;


@Service("uacMenuService")
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class UacMenuServiceImpl extends ServiceImpl<UacMenuDao, UacMenuEntity> implements UacMenuService {

    @Resource
    private UacMenuDao uacMenuDao;

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<UacMenuEntity> getMenuList(Long userId, Long applicationId) {
        // 1.查询该用户下所有的菜单列表
        List<UacMenuEntity> menuList = Lists.newArrayList();
        // 如果是admin则返回所有的菜单
        if (userId == 1L) {
            // 1.1 查询该用户下所有的菜单列表
            Wrapper queryWrapper =  new QueryWrapper<>()
                    .eq("status",UacMenuStatusEnum.ENABLE.getType())
                    .eq(applicationId!=null,"application_id",applicationId)
                    .ne("id",1L)
                    .orderByAsc("level")
                    .orderByAsc("number");
            menuList = uacMenuDao.selectList(queryWrapper);
        } else {
            // 1.2查询该用户下所有的菜单列表
            menuList = uacMenuDao.findMenuListByUserId(userId);
        }
        return menuList;
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<Tree<Long>> getMenuTree(String comCode, Long applicationId) {
        Wrapper queryWrapper =  new QueryWrapper<>()
                .eq("status",UacMenuStatusEnum.ENABLE.getType())
                .eq(applicationId!=null,"application_id",applicationId)
                .orderByAsc("level")
                .orderByAsc("number");
        List<UacMenuEntity> menuList = uacMenuDao.selectList(queryWrapper);

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setParentIdKey("pid");
        treeNodeConfig.setWeightKey("seq");
        treeNodeConfig.setNameKey("label");
        treeNodeConfig.setChildrenKey("children");
        treeNodeConfig.setDeep(5);
        List<Tree<Long>> treeList = TreeUtil.build(menuList, 0L, treeNodeConfig, (treeNode, tree) -> {
            tree.setId(treeNode.getId());
            tree.setParentId(treeNode.getPid());
            tree.setWeight(treeNode.getNumber());
            tree.setName(treeNode.getMenuName());
        });
        return treeList;
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public ViewMenuVo getViewVoById(Long id) {
        Preconditions.checkArgument(id != null, "菜单ID不能为空");
        UacMenuEntity uacMenuEntity = this.getById(id);

        if (uacMenuEntity == null) {
            log.error("找不到菜单信息id={}", id);
            throw new UacBizException(ErrorCodeEnum.UAC10013003, id);
        }
        // 获取父级菜单信息
        UacMenuEntity parentMenu = this.getById(uacMenuEntity.getPid());
        ModelMapper modelMapper = new ModelMapper();
        ViewMenuVo menuVo = modelMapper.map(uacMenuEntity, ViewMenuVo.class);

        if (parentMenu != null) {
            menuVo.setParentMenuName(parentMenu.getMenuName());
        }
        return menuVo;
    }

    @Override
    public boolean saveUacMenu(UacMenuEntity menu, LoginAuthDto loginAuthDto) {
        Long pid = menu.getPid();
        menu.setUpdateInfo(loginAuthDto);
        UacMenuEntity parentMenu = this.getById(pid);
        if (PublicUtil.isEmpty(parentMenu)) {
            throw new UacBizException(ErrorCodeEnum.UAC10013001, pid);
        }
        if (menu.isNew()) {
            UacMenuEntity updateMenu = new UacMenuEntity();
            menu.setLevel(parentMenu.getLevel() + 1);
            updateMenu.setLeaf(MenuConstant.MENU_LEAF_NO);
            updateMenu.setId(pid);

            boolean result = this.updateById(updateMenu);

            if (!result) {
                //throw new UacBizException(ErrorCodeEnum.UAC10013002, menuId);
            }

            menu.setStatus(UacMenuStatusEnum.ENABLE.getType());
            menu.setCreatorId(loginAuthDto.getUserId());
            menu.setCreator(loginAuthDto.getUserName());
            menu.setLastOperatorId(loginAuthDto.getUserId());
            menu.setLastOperator(loginAuthDto.getUserName());
            // 新增的菜单是叶子节点
            menu.setLeaf(MenuConstant.MENU_LEAF_YES);
            return this.save(menu);
        } else {
            return this.updateById(menu);
        }
    }

    @Override
    public boolean deleteUacMenuById(Long id, LoginAuthDto loginAuthDto) {
        Preconditions.checkArgument(id != null, "菜单id不能为空");
        boolean result;
        // 获取当前菜单信息
        UacMenuEntity uacMenuQuery = this.getById(id);

        if (PublicUtil.isEmpty(uacMenuQuery)) {
            throw new UacBizException(ErrorCodeEnum.UAC10013003, id);
        }

        // 删除菜单与角色的关联关系
        UacRoleMenuEntity uacRoleMenu = new UacRoleMenuEntity();
        uacRoleMenu.setMenuId(id);
        //uacRoleMenuService.delete(uacRoleMenu);


        // 删除菜单
        result = this.removeById(id);
        if (!result) {
            log.error("删除菜单失败 menuId={}", id);
            throw new UacBizException(ErrorCodeEnum.UAC10013008, id);
        }

        // 删除权限
        // TODO 应该先查询再删除
        //uacActionService.deleteByMenuId(id);

        // 修改当前删除菜单的父菜单是否是叶子节点
        UacMenuEntity updateParentUacMenu = new UacMenuEntity();
        updateParentUacMenu.setId(uacMenuQuery.getPid());
        updateParentUacMenu.setLeaf(MenuConstant.MENU_LEAF_YES);
        // 是二三级
        if (Objects.equals(MenuConstant.MENU_LEVEL_TWO, uacMenuQuery.getLevel()) || Objects.equals(MenuConstant.MENU_LEVEL_THREE, uacMenuQuery.getLevel())) {
            // 查询是否是叶子节点
            int count = this.count(new QueryWrapper<UacMenuEntity>().eq("pid",uacMenuQuery.getPid()));
            if (count == 0) {
                this.updateById(updateParentUacMenu);
            }
        }
        return result;
    }

    @Override
    public List<UacMenuEntity> listMenuListByRoleId(Long roleId) {
        List<UacMenuEntity> menuList = uacMenuDao.listMenuListByRoleId(roleId);
        Set<Long> ids = new HashSet<>();
        if (PublicUtil.isNotEmpty(menuList)) {
            for (UacMenuEntity uacMenu : menuList) {
                ids.add(uacMenu.getId());
                getMenuIds(ids, uacMenu.getPid());
            }
        }
        List<UacMenuEntity> allMenus =  null;
        if(PublicUtil.isNotEmpty(ids)){
            allMenus = uacMenuDao.selectBatchIds(ids);
        }
        return allMenus;
    }
    private Set<Long> getMenuIds(Set<Long> ids, Long menuId) {
        UacMenuEntity uacMenu = uacMenuDao.selectById(menuId);
        if (uacMenu != null) {
            Long pid = uacMenu.getPid();
            if (pid != null) {
                ids.add(pid);
                getMenuIds(ids, pid);
            }
        }
        return ids;
    }

    @Override
    public List<Long> getCheckedMenuList(Long roleId) {
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
        return uacMenuDao.getCheckedMenuList(roleId);
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public boolean checkMenuHasChildMenu(Long pid) {
        Preconditions.checkArgument(pid != null, "菜单pid不能为空");

        UacMenuEntity uacMenu = new UacMenuEntity();
        uacMenu.setStatus(UacMenuStatusEnum.ENABLE.getType());
        uacMenu.setPid(pid);
        QueryWrapper<UacMenuEntity> queryWrapper = new QueryWrapper<>(uacMenu);
        return this.count(queryWrapper) > 0;
    }
    
    /**
     * 根据menuid查询自身和父级菜单
     * @param menuList
     * @return
     */
//    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
	public List<UacMenuEntity> getMenuTreeByMenuId(List<UacMenuEntity> menuList){
    	 return uacMenuDao.getMenuTreeByMenuId(menuList);
    }
}